﻿using Basic.FormCollect;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.PhyFormInter;
using Basic.FormRemoteModel.PhyFormInter.Model;
using Basic.FormRemoteModel.QueryInter.Model;
using Basic.FormRemoteModel.TableRecord.Model;
using Basic.UserFormService.Interface;
using Basic.UserFormService.Model.PhyForm;
using WeDonekRpc.Helper;

namespace Basic.UserFormService.lmpl
{
    internal class PhyFormRowService : IPhyFormRowService
    {
        private readonly IPhysicalFormGroupCollect _PhyGroup;
        private readonly IPhysicalTableCollect _PhyTable;
        private readonly IPhysicalColumnCollect _PhyColumn;
        public PhyFormRowService ( IPhysicalFormGroupCollect phyGroup,
            IPhysicalTableCollect phyTable,
            IPhysicalColumnCollect phyColumn )
        {
            this._PhyGroup = phyGroup;
            this._PhyTable = phyTable;
            this._PhyColumn = phyColumn;
        }

        public bool AddRow ( Dictionary<long, FormVal> vals, PhyFormBase form, TableDataRow row )
        {
            PhyTable[] tables = this._PhyTable.GetsByFormId<PhyTable>(form.Id);
            if ( tables.IsNull() )
            {
                return false;
            }
            PhyTableColumn[] cols = this._PhyColumn.GetsByFormId<PhyTableColumn>(form.Id, null, null);
            if ( cols.IsNull() )
            {
                return false;
            }
            Dictionary<long, FormVal> values = row.Relation.ToDictionary(a => a.ToColId, a => vals.GetValueOrDefault(a.ColId));
            PhyTableRecord[] records = this._GetRecord(tables, cols, values);
            PhyFormGroup group = this._PhyGroup.Get<PhyFormGroup>(form.PhyGroupId.Value);
            new AddPhyTableRow
            {
                TableName = form.PhyTableName,
                LinkPK = row.LinkPK,
                LinkType = row.LinkType,
                Records = records,
            }.Send(group.SysTypeVal);
            return true;
        }
        private PhyTableRecord[] _GetRecord ( PhyTable[] tables, PhyTableColumn[] cols, Dictionary<long, FormVal> values )
        {
            return tables.ConvertAll(a =>
            {
                PhyTableColumn[] columns = cols.FindAll(c => c.PhyTableId == a.Id);
                PhyTableRecord record = new PhyTableRecord
                {
                    TableName = a.TableName,
                    Colnum = columns.ToDictionary(c => c.Name, c => new ColStruct
                    {
                        DataType = c.DataType,
                        FuncType = c.FuncType,
                    })
                };
                if ( a.TableType == FormTableType.单一表单 )
                {
                    record.Row = new PhyTableRow
                    {
                        Index = 0,
                        Column = columns.ToDictionary(c => c.Name, c =>
                        {
                            if ( values.TryGetValue(c.Id, out FormVal val) && !val.IsNull )
                            {
                                return new PhyTableColValue
                                {
                                    BoolVal = val.BoolVal,
                                    IsNull = val.IsNull,
                                    LongVal = val.LongVal,
                                    NumVal = val.NumVal,
                                    StrVal = val.StrVal,
                                    Vals = val.Vals
                                };
                            }
                            return new PhyTableColValue
                            {
                                IsNull = true
                            };
                        })
                    };
                }
                else
                {
                    int len = 0;
                    foreach ( PhyTableColumn col in columns )
                    {
                        if ( values.TryGetValue(col.Id, out FormVal val) && val.IsNull == false )
                        {
                            len = val.ListItem.Len;
                            break;
                        }
                    }
                    if ( len > 0 )
                    {
                        record.Rows = len.For<PhyTableRow>(i =>
                        {
                            return new PhyTableRow
                            {
                                Index = i,
                                Column = columns.ToDictionary(c => c.Name, c =>
                                {
                                    if ( values.TryGetValue(c.Id, out FormVal val) && !val.IsNull )
                                    {
                                        return this._GetValue(val.ListItem, i);
                                    }
                                    return new PhyTableColValue
                                    {
                                        IsNull = true
                                    };
                                })
                            };
                        });
                    }
                }
                return record;
            });
        }
        private PhyTableColValue _GetValue ( FormListItem item, int index )
        {
            if ( item.DataType == FormRecordDataType.Bool )
            {
                bool? val = item.BoolVal[index];
                return new PhyTableColValue
                {
                    IsNull = val.HasValue == false,
                    BoolVal = val,
                };
            }
            else if ( item.DataType == FormRecordDataType.Number )
            {
                decimal? val = item.NumVal[index];
                return new PhyTableColValue
                {
                    IsNull = val.HasValue == false,
                    NumVal = val
                };
            }
            else if ( item.DataType == FormRecordDataType.Array )
            {
                string[] val = item.Vals[index];
                return new PhyTableColValue
                {
                    IsNull = val.IsNull(),
                    Vals = val
                };
            }
            else if ( item.DataType == FormRecordDataType.Date ||
                item.DataType == FormRecordDataType.DateTime ||
                item.DataType == FormRecordDataType.Long ||
                item.DataType == FormRecordDataType.Time )
            {
                long? val = item.LongVal[index];
                return new PhyTableColValue
                {
                    IsNull = val.HasValue == false,
                    LongVal = val
                };
            }
            else
            {
                string val = item.StrVal[index];
                return new PhyTableColValue
                {
                    IsNull = val.IsNull(),
                    StrVal = val
                };
            }
        }
    }
}
